﻿Imports MT2SP.blog
Imports System.Xml
Imports System.Xml.Xsl
Imports System.IO
Imports Microsoft.SharePoint.Utilities
Imports MT2SP.localhost
Imports MT2SP.sptest





Public Class Form1
    Private brunning As Boolean = True
    Dim categories As Microsoft.SharePoint.SPListItemCollection
    Dim lerrors As Long = 0
    Dim bDryRun As Boolean = False

    Private Function CAMLCleaner(ByVal sCAML As String) As String
        'XML Cleaning < > & "
        'replace quote
        Dim sCAMLtemp = Replace(sCAML, ControlChars.Quote, "'")
        'replace single quote
        'sCAMLtemp = Replace(sCAMLtemp, "'", "&apos;")
        'replace &
        sCAMLtemp = Replace(sCAMLtemp, "&", "&amp;")
        'replace <
        ' sCAMLtemp = Replace(sCAMLtemp, "<", "&lt;")
        'replace >
        ' sCAMLtemp = Replace(sCAMLtemp, ">", "&gt;")

        CAMLCleaner = sCAMLtemp

    End Function
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        txtFilePath.Text = My.Settings.BlogImportFilePath
        cboPostList.DropDownStyle = ComboBoxStyle.DropDownList
        cboCommentsList.DropDownStyle = ComboBoxStyle.DropDownList
        txtUserName.Text = My.Settings.defaultUserName
        txtr1left.Text = My.Settings.sr1_OldAttLocation
        txtr1right.Text = My.Settings.sr1_NewAttLocation
        txtr2left.Text = My.Settings.sr2_OldAttLocation
        txtr2right.Text = My.Settings.sr2_NewAttLocation
        txtr3left.Text = My.Settings.sr3_OldAttLocation
        txtr3right.Text = My.Settings.sr3_NewAttLocation

        'form url rather than use settings (as i need to use it elsewhere, split
        textWS.Text = "http://" & Trim(txtSiteRoot.Text) & "/" & Trim(txtSiteSub.Text) & "/" & Trim(txtSitePage.Text)

        Me.Text = Application.ProductName + " " + Application.ProductVersion

        Button1_Click_1()
    End Sub
    Private Function LoadCategories() As Boolean
        '{4CF1D2BB-7EDC-4F63-8191-905C9B5195C5}
        ' Connect to the server
        Dim L As New localhost.Lists
        L.Credentials = System.Net.CredentialCache.DefaultCredentials
        ' Arguments required by GetListItems
        Dim viewName As String
        Dim query As System.Xml.XmlNode
        Dim viewFields As System.Xml.XmlNode
        Dim rowLimit As String
        Dim queryOptions As System.Xml.XmlNode
        ' Get the items from the list specified
        ' by the current row in the DataGrid

        Dim camlDocument As XmlDocument = New XmlDocument()
        Dim queryNode As XmlNode = camlDocument.CreateElement("Query")
        'queryNode.InnerXml = "<OrderBy><FieldRef Name='Title' /></OrderBy><Where>" + "<Eq><FieldRef Name='Title' /><Value Type='Text'>Art</Value></Eq>" + "</Where>"
        queryNode.InnerXml = "<OrderBy><FieldRef Name='Title' /></OrderBy>"

        Dim spurl As String = "http://" & txtSiteRoot.Text & "/" & txtSiteSub.Text

        RichTextBox1.AppendText("Caching categories from " & spurl & vbCrLf)

        Dim spsite As New Microsoft.SharePoint.SPSite(spurl)

        Dim SPQuery As New Microsoft.SharePoint.SPQuery
        Dim SPWeb As Microsoft.SharePoint.SPWeb

        Dim splist As Microsoft.SharePoint.SPList


        Try
            SPQuery.Query = queryNode.InnerXml
            SPWeb = spsite.OpenWeb()
            splist = SPWeb.Lists("categories")

            categories = splist.GetItems(SPQuery)

            If categories.Count = 0 Then
                RichTextBox1.AppendText("Unable to cache category list" & vbCrLf)
                Return False
            End If

        Catch ex As Exception
            RichTextBox1.AppendText("Unable to connect to category list: " & ex.ToString & vbCrLf)
        End Try


        RichTextBox1.AppendText("cached " & categories.Count.ToString & " categories " & vbCrLf)
        Return True

    End Function

    Public Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.

    End Sub

  


    Public Function GetCategory(ByVal vcat As String, ByVal vblog As String) As String
        If Not vcat = Nothing Then vcat = vcat.ToUpper '.Replace(" ", "")
        Dim catcode As String = ""
        Dim camlDocument As XmlDocument = New XmlDocument()
        Dim queryNode As XmlNode = camlDocument.CreateElement("Query")

        querynode.InnerXml = "<OrderBy><FieldRef Name='Title' /></OrderBy>"
        Dim SPQuery As New Microsoft.SharePoint.SPQuery
        SPQuery.Query = querynode.InnerXml

        Dim SPLI As Microsoft.SharePoint.SPListItem

        Dim bfound As Boolean = False

        RichTextBox1.AppendText("Looking for category [" & vcat.ToString & "] in Category Cache" & vbCrLf)

        For Each SPLI In categories
            If UCase(vcat) = UCase(SPLI.Title) Then
                'MsgBox("matched " & SPLI.ID)

                catcode = SPLI.ID & ";#" & SPLI.Title
                RichTextBox1.AppendText("Found category [" & vcat.ToString & "]|" & catcode & vbCrLf)
                bfound = True
                Exit For

            End If
        Next

        If Not bfound Then
            RichTextBox2.AppendText("Unable to find category [" & vcat.ToString & "] in cache" & vbCrLf)
        Else
            catcode = catcode.ToString + ";"
        End If

        GetCategory = catcode.ToString

    End Function
    Private Function FormCategoryString(ByRef vblogitem As BlogItem) As String

        FormCategoryString = "undefined"

        RichTextBox1.AppendText("form category string" & vbCrLf)

        If Not vblogitem.CATEGORY = Nothing Then
            Dim i, iSplitCount As Integer

            Dim arySplits() As String
            Dim stringtosplit As String = vblogitem.CATEGORY.Replace("CATEGORY:", "!")


            arySplits = stringtosplit.Split("!")
            RichTextBox1.AppendText("-----------------------------------------------------" & vbCrLf & vbCrLf)
            RichTextBox1.AppendText(vblogitem.CATEGORY & " splits into " & arySplits.Count & vbCrLf & vbCrLf)

            If arySplits.Count > 1 Then
                Debug.Print("2")
            End If
            Dim sReformedTagString As String = ""

            For arloop = 0 To arySplits.Count - 1
                RichTextBox1.AppendText("split " & arloop.ToString & " : " & arySplits(arloop).ToString & vbCrLf & vbCrLf)
                Dim cleaned As String = arySplits(arloop).Replace("ATEGORY: ", "").Trim
                Dim newcategory As String = GetCategory(cleaned, My.Settings.blog)
                RichTextBox1.AppendText("attempted match on (" & cleaned & "):" & newcategory & vbCrLf & vbCrLf)
                If newcategory = "" Then
                    RichTextBox2.AppendText("No category match for:" & cleaned & vbCrLf & vbCrLf)
                    lerrors = lerrors + 1
                    lblErrors.Text = lerrors.ToString
                Else
                    sReformedTagString = sReformedTagString + newcategory + "#"
                End If
            Next
            RichTextBox1.AppendText("New Category string:" & sReformedTagString & vbCrLf & vbCrLf)
            RichTextBox1.AppendText("-----------------------------------------------------" & vbCrLf & vbCrLf)
            FormCategoryString = sReformedTagString
        Else
            'no category on orig post, so return empty string
            FormCategoryString = ""

        End If

        Return FormCategoryString


    End Function
    

    Private Sub Button1_Click_1() Handles Button1.Click
        Try
            ' Get the list of lists from the server
            Dim L As New localhost.Lists

            If My.Settings.Proxy <> "" Then
                L.Proxy = New System.Net.WebProxy(My.Settings.Proxy, True)
                L.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials
            End If




            L.Credentials = System.Net.CredentialCache.DefaultCredentials
            RichTextBox1.Clear()
            RichTextBox2.Clear()
            cboPostList.Items.Clear()
            cboCommentsList.Items.Clear()
            If bDryRun Then RichTextBox1.AppendText("*** DRY RUN, NO DATA WILL BE LOADED ***" & vbCrLf)

            RichTextBox1.AppendText("Attempting connection to web service:" & textWS.Text & vbCrLf & vbCrLf)

            Application.DoEvents()

            L.Url = textWS.Text


            ' The list is returned as an XmlNode object
            Dim n As XmlNode = L.GetListCollection
            ' Prepare objects to handle the data
            Dim xd As XmlDataDocument = New XmlDataDocument
            Dim ds As DataSet = xd.DataSet
            ds.ReadXmlSchema(My.Settings.ListsXSDPath)
            ' Add an XML declaration to make the 
            ' XmlNode a valid XML document
            xd.LoadXml("<?xml version='1.0' ?>" & n.OuterXml)
            Dim dr As DataRow
            Dim dt As DataTable



            dt = ds.Tables(0)
            Dim idefaultPostsItem As Integer = -1
            Dim iDefaultCommentsItem As Integer = -1
            Dim iLoop As Integer = 0
            For Each dr In dt.Rows
                'dr(3) - title
                cboPostList.Items.Add(dr(3) & " " & dr(2))
                If dr(3).ToString.ToUpper = "POSTS" Then
                    idefaultPostsItem = iLoop
                End If


                cboCommentsList.Items.Add(dr(3) & " " & dr(2))
                If dr(3).ToString.ToUpper = "COMMENTS" Then
                    iDefaultCommentsItem = iLoop
                End If
                iLoop = iLoop + 1

            Next
            cboPostList.SelectedIndex = idefaultPostsItem
            cboCommentsList.SelectedIndex = iDefaultCommentsItem

            If idefaultPostsItem = -1 Then
                RichTextBox1.AppendText("*Could not find a list named Posts, are you sure " & textWS.Text & " is the right WS address for a CKS:EBE blog?" & vbCrLf)
            End If

            If iDefaultCommentsItem = -1 Then
                RichTextBox1.AppendText("*Could not find a list named Comments, are you sure " & textWS.Text & " is the right WS address for a CKS:EBE blog?" & vbCrLf)
            End If

            RichTextBox1.AppendText("Connected to WS:" & textWS.Text & ", no error occurred" & vbCrLf)
            If iDefaultCommentsItem <> -1 And idefaultPostsItem <> -1 Then
                RichTextBox1.AppendText("Site at " & textWS.Text & " appears to be a CKS:EBE blog!" & vbCrLf)
            End If

            LoadCategories()

            Panel3.Enabled = True
        Catch ex As Exception
            RichTextBox1.AppendText("Error:" & ex.ToString)
            Panel3.Enabled = False
        End Try

    End Sub

    Private Sub Button7_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button7.Click
        Button1_Click_1()

        If cboPostList.SelectedIndex = -1 Or cboCommentsList.SelectedIndex = -1 Or txtUserName.Text.Length = 0 Or txtFilePath.TextLength = 0 Then
            MsgBox("Please enter all info!", MsgBoxStyle.Critical)
            Exit Sub
        End If
        Button9.Visible = True
        Button7.Enabled = False
        Me.Cursor = Cursors.AppStarting
        GroupBox4.Enabled = False

        brunning = True
        lerrors = 0

        Try
            'RichTextBox1.Clear()
            RichTextBox1.AppendText("Loading items from blog export:" & txtFilePath.Text & vbCrLf & vbCrLf)
            'load the file
            Application.DoEvents()

            Dim bloglist As New blog(txtFilePath.Text)
            Application.DoEvents()

            RichTextBox1.AppendText("Total of " & bloglist.BlogItems.Count & " Blog posts loaded" & vbCrLf)

            If bloglist.BlogItems.Count = 0 Then
                RichTextBox1.AppendText("Is this a valid file?" & vbCrLf & vbCrLf)
            Else
                RichTextBox1.AppendText("Processing blog items via WS:" & textWS.Text & vbCrLf & vbCrLf)
                'MsgBox(bloglist.BlogItems.Count)

            End If

            Dim blogitem As BlogItem

            ProgressBar1.Step = 2

            ProgressBar1.Maximum = bloglist.BlogItems.Count
            Dim loopcount As Long = 0

            For Each blogitem In bloglist.BlogItems
                If brunning = False Then Exit For
                RichTextBox1.AppendText("------------------------------------------------" & vbCrLf)
                Dim mylist = New localhost.Lists()
                mylist.Credentials = System.Net.CredentialCache.DefaultCredentials
                mylist.Url = textWS.Text


                Dim doc As New XmlDocument()
                Dim batch As XmlElement
                batch = doc.CreateElement("Batch")

                Dim publisheddate As DateTime = Now
                'Dim spublishedDate As String = Microsoft.SharePoint.Utilities.SPUtility.CreateISO8601DateTimeFromSystemDateTime(publisheddate)
                Dim spublishedDate As String = Microsoft.SharePoint.Utilities.SPUtility.CreateISO8601DateTimeFromSystemDateTime(blogitem.BlogDATE)
                Dim BlogTitleForURL As String = System.Text.RegularExpressions.Regex.Replace(blogitem.TITLE, " ", String.Empty, System.Text.RegularExpressions.RegexOptions.IgnoreCase)

                Dim sPreviousAttLocation1 = txtr1left.Text
                Dim sNewAttLocation1 = txtr1right.Text
                Dim sPreviousAttLocation2 = txtr2left.Text
                Dim sNewAttLocation2 = txtr2right.Text
                Dim sPreviousAttLocation3 = txtr3left.Text
                Dim sNewAttLocation3 = txtr3right.Text

                Dim sBlogCategory As String = FormCategoryString(blogitem)
                lblErrors.Text = lerrors.ToString

                Dim sFindString As String = ""
                Dim sBlogBodyclean As String
                RichTextBox1.AppendText("cleaning body text...." & vbCrLf)
                sBlogBodyclean = Replace(blogitem.BODY, sPreviousAttLocation1, sNewAttLocation1)
                sBlogBodyclean = Replace(sBlogBodyclean, sPreviousAttLocation2, sNewAttLocation2)
                sBlogBodyclean = Replace(sBlogBodyclean, sPreviousAttLocation3, sNewAttLocation3)

                'RichTextBox1.AppendText("cleaned body text:" & sBlogBodyclean & vbCrLf & vbCrLf)
                RichTextBox1.AppendText("cleaned body text" & vbCrLf)

                'Dim BlogBody As String = "<div class='tagged'><br/><h3>DEBUG<br/><strong>This post has been migrated from MovableType, " & blogitem.AUTHOR & " was the original author</strong><br/>Blog category original:" & blogitem.CATEGORY & "<br/>New category string:" & sBlogCategory & "</h3><br/></div><br/>" & sBlogBodyclean
                Dim BlogBody As String = sBlogBodyclean
                'Dim BlogBody As String = "***post body here***"
                'MsgBox(blogitem.BODY, , "orig")
                'MsgBox(CAMLCleaner(blogitem.BODY), , "new")
                batch.InnerXml = "<Method ID='1' Cmd='New'>" & _
                          "<Field Name='Title'>" + CAMLCleaner(blogitem.TITLE.ToString) + "</Field>" & _
                  "<Field Name='Body'><![CDATA[" + BlogBody.ToString + "]]></Field>" & _
                "<Field Name='PublishedDate'>" & spublishedDate & "</Field>" & _
                "<Field Name='BlogTitleForUrl'>" + CAMLCleaner(BlogTitleForURL) + "</Field>" & _
                 "<Field Name='Categories' Type='Lookup'>" + sBlogCategory + "</Field>" & _
                "<Field Name='ManualTrackbackPing'>Manual trackback</Field>" & _
                "<Field Name='Author'>" + txtUserName.Text + "</Field>" & _
            "<Field Name='Editor'>" + txtUserName.Text + "</Field>" & _
        "</Method>"

                Dim listGUID As String = cboPostList.SelectedItem.ToString
                Dim commlistGUID As String = cboCommentsList.SelectedItem.ToString

                Dim sBlogListGUID As String
                Dim sBlogCommentsListGUID As String

                sBlogListGUID = listGUID.Substring(listGUID.IndexOf("{"), listGUID.Length - listGUID.IndexOf("{"))
                sBlogCommentsListGUID = commlistGUID.Substring(commlistGUID.IndexOf("{"), commlistGUID.Length - commlistGUID.IndexOf("{"))

                'RichTextBox1.AppendText("Attempting data injection via WS:" & My.Settings.BlogPostListGUID & vbCrLf & vbCrLf)
                RichTextBox1.AppendText("Attempting data injection via WS:" & sBlogListGUID & vbCrLf & vbCrLf)

                Dim sPostID As String
                Dim returnNode As XmlNode

                Try

                    'Dim returnNode As XmlNode = mylist.UpdateListItems("{4CF1D2BB-7EDC-4F63-8191-905C9B5195C5}", batch)
                    If Not bDryRun Then
                        returnNode = mylist.UpdateListItems(sBlogListGUID, batch)

                        If returnNode.InnerText <> "0x00000000" Then
                            RichTextBox2.AppendText("error:" & blogitem.CATEGORY & " = " & sBlogCategory & vbCrLf & returnNode.InnerText & vbCrLf & vbCrLf)
                            lerrors = lerrors + 1

                        Else
                            RichTextBox1.AppendText("Injection complete" & vbCrLf)
                        End If
                    End If

                    Application.DoEvents()


                    Dim resultNode As XmlNode = returnNode.FirstChild

                    For Each childNode As XmlNode In resultNode.ChildNodes
                        For Each attrib As XmlAttribute In childNode.Attributes
                            'MsgBox(attrib.Name.ToString)
                            'Debug.Print(attrib.Name)
                            'RichTextBox1.AppendText(attrib.Name & vbCrLf & vbCrLf)

                            If attrib.Name = "ows_ID" Then sPostID = attrib.Value

                            If (attrib.Name = "ows_SelectTitle") Then
                                'MsgBox(attrib.Value)
                                Exit For
                            End If

                        Next
                        lblErrors.Text = lerrors.ToString

                    Next
                Catch ex As Exception
                    RichTextBox2.AppendText("Failed to inject via WS:" & textWS.Text & "[" & blogitem.TITLE.ToString & "]" & vbCrLf)
                    'Throw New Exception("Failed to inject via WS:" & My.Settings.BlogPostListGUID & " : " & ex.ToString)
                End Try


                'comments
                If blogitem.blogcomments.Count > 0 Then
                    Dim blogComment As BlogComments

                    'For Each blogitem In bloglist.BlogItems
                    Dim commentcount As Integer = 0

                    batch = doc.CreateElement("Batch")



                    For Each blogComment In blogitem.blogcomments
                        'MsgBox("postid=" & sPostID & "comment:" & blogitem.blogcomments(commentcount).COMMENT)
                        publisheddate = Now
                        'Dim spublishedDate As String = Microsoft.SharePoint.Utilities.SPUtility.CreateISO8601DateTimeFromSystemDateTime(publisheddate)
                        spublishedDate = Microsoft.SharePoint.Utilities.SPUtility.CreateISO8601DateTimeFromSystemDateTime(blogitem.blogcomments(commentcount).CommentDATE)
                        'BlogTitleForURL = System.Text.RegularExpressions.Regex.Replace(blogitem.TITLE, " ", String.Empty, System.Text.RegularExpressions.RegexOptions.IgnoreCase)

                        Dim CommentBody As String = "<b>This post has been migrated from MovableType, " & blogitem.AUTHOR & " was the original author </b><BR><BR>" & blogitem.BODY
                        'MsgBox(blogitem.BODY, , "orig")
                        'MsgBox(CAMLCleaner(blogitem.BODY), , "new")
                        batch.InnerXml = "<Method ID='1' Cmd='New'>" & _
                                  "<Field Name='Title'>" + CAMLCleaner(blogitem.blogcomments(commentcount).AUTHOR) + "</Field>" & _
                          "<Field Name='Body'><![CDATA[" + blogitem.blogcomments(commentcount).COMMENT + "]]></Field>" & _
                        "<Field Name='PostTitle' Type='Lookup'>" + sPostID + "</Field>" & _
                        "</Method>"
                        ' "<Field Name='ID'>New</Field>" & _

                        '"<Field Name='Created_x0020_By'></Field>" & _
                        '"<Field Name='Modified_x0020_By'></Field>" & _




                        'Dim sBlogCommentGUID = My.Settings.BlogCommentListGUID
                        'returnNode = mylist.UpdateListItems(sBlogCommentGUID, batch)
                        If Not bDryRun Then
                            returnNode = mylist.UpdateListItems(sBlogCommentsListGUID, batch)

                            If returnNode.InnerText <> "0x00000000" Then
                                RichTextBox2.AppendText("error inserting comment:")
                                RichTextBox2.AppendText(batch.ToString)
                                lerrors = lerrors + 1
                            Else
                                RichTextBox1.AppendText("Comment Injection complete for " & blogitem.TITLE.ToString & vbCrLf)
                            End If
                        End If

                        Application.DoEvents()
                        'MsgBox(returnNode.InnerText)

                    Next
                End If
                RichTextBox1.AppendText("------------------------------------------------" & vbCrLf)
                RichTextBox1.ScrollToCaret()
                RichTextBox2.ScrollToCaret()
                ProgressBar1.Value = loopcount
                loopcount = loopcount + 1

                Application.DoEvents()


            Next

            Dim sresponse As String
            sresponse = "Process complete"
            If brunning = False Then sresponse = sresponse + " *Aborted*"

            RichTextBox1.AppendText(sresponse & vbCrLf)

            MsgBox(sresponse, MsgBoxStyle.Information)



        Catch ex As Exception
            RichTextBox2.AppendText("Failed:" & ex.ToString & vbCrLf & vbCrLf)
        Finally
            Button7.Enabled = True
            Me.Cursor = Cursors.Default
            Button9.Visible = False
            GroupBox4.Enabled = True

        End Try

    End Sub

    Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click
        brunning = False
    End Sub

    Private Sub cboLists_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)

    End Sub

    Private Sub cboLists_SelectedIndexChanged_1(ByVal sender As System.Object, ByVal e As System.EventArgs)
        RichTextBox1.AppendText("Target post list changed to " & cboPostList.SelectedItem & vbCrLf & vbCrLf)
    End Sub

    Private Sub cboCommentsList_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
        RichTextBox1.AppendText("Target comments list changed to " & cboCommentsList.SelectedItem & vbCrLf & vbCrLf)
    End Sub

    Private Sub GroupBox4_Enter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GroupBox4.Enter

    End Sub

    Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
        Dim fdlg As OpenFileDialog = New OpenFileDialog()
        fdlg.Title = "MT Export File"
        fdlg.InitialDirectory = "c:\"
        fdlg.Filter = "All files (*.*)|*.*|All files (*.*)|*.*"
        fdlg.FilterIndex = 2
        fdlg.RestoreDirectory = True

        If fdlg.ShowDialog() = DialogResult.OK Then
            txtFilePath.Text = fdlg.FileName
            RichTextBox1.AppendText("Source file changed to:" & fdlg.FileName & vbCrLf)
        End If
    End Sub

    
    Private Sub textWS_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles textWS.TextChanged
        Panel3.Enabled = False
    End Sub

    Private Sub txtSiteRoot_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSiteRoot.TextChanged
        textWS.Text = "http://" & Trim(txtSiteRoot.Text) & "/" & Trim(txtSiteSub.Text) & "/" & Trim(txtSitePage.Text)
    End Sub

    Private Sub txtSiteSub_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSiteSub.TextChanged
        textWS.Text = "http://" & Trim(txtSiteRoot.Text) & "/" & Trim(txtSiteSub.Text) & "/" & Trim(txtSitePage.Text)
    End Sub

    Private Sub txtSitePage_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSitePage.TextChanged
        textWS.Text = "http://" & Trim(txtSiteRoot.Text) & "/" & Trim(txtSiteSub.Text) & "/" & Trim(txtSitePage.Text)
    End Sub

    Private Sub chkDryRun_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles chkDryRun.CheckedChanged
        bDryRun = chkDryRun.Checked
    End Sub
End Class
